package com.quectel.emp.util;

import com.google.common.base.Preconditions;
import com.quectel.constant.global.SystemConstants;
import com.quectel.core.module.dept.dto.DeptPersonDto;
import com.quectel.emp.constants.EmpSystemConstants;
import com.quectel.emp.interceptor.LoginEmpSession;
import com.quectel.emp.service.deptperson.ApiDeptPersonService;
import com.quectel.util.common.JacksonUtils;
import com.quectel.util.redis.RedisUtils;
import com.quectel.util.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * session管理器
 *
 * @author: caolu
 * @email: louis.cao@quectel.com
 * @date: 2022-07-27 10:46:00
 */
@Slf4j
public class SessionHolder {


    /**
     * 得到session
     *
     * @return
     */
    public static LoginEmpSession getLoginEmpSession() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Preconditions.checkArgument(requestAttributes != null, "ServletRequestAttributes is null");
        HttpServletRequest httpServletRequest = requestAttributes.getRequest();
        Preconditions.checkArgument(httpServletRequest != null, "HttpServletRequest is null");

        String token = httpServletRequest.getHeader("token");
        log.debug("token --- " + token);
        if (org.apache.commons.lang3.StringUtils.isEmpty(token)) {
            token = httpServletRequest.getParameter("token");
        }
        if (StringUtils.isNotBlank(token)) {
            //header和url都没有传入token
            LoginEmpSession session = (LoginEmpSession) httpServletRequest.getAttribute(EmpSystemConstants.TOKEN_EMP_SESSION);
            if (session != null) {
                return session;
            }
            String sessionStr = RedisUtils.get(EmpSystemConstants.TOKEN_EMP_SESSION + token);
            if (StringUtils.isNotBlank(sessionStr)) {
                return JacksonUtils.parse(sessionStr, LoginEmpSession.class);
            }
        }
        return null;
    }

    /**
     * 得到员工信息
     *
     * @return
     */
    public static DeptPersonDto getEmp() {
        if (getLoginEmpSession() != null && getLoginEmpSession().getDeptPersonDto() != null) {
            return getLoginEmpSession().getDeptPersonDto();
        }
        return null;
    }

    public static void checkEmp() {
        LoginEmpSession session = getLoginEmpSession();
        Preconditions.checkNotNull(session);
    }


    /**
     * 修改session信息
     *
     * @param modifiedSession 被修改过的session
     * @return
     */
    public static LoginEmpSession resetLoginEmpSession(LoginEmpSession modifiedSession) {

        if (modifiedSession.getDeptPersonDto() != null) {
            //双向绑定
            RedisUtils.hSet(
                    EmpSystemConstants.EMP_TOKEN_SESSION + modifiedSession.getDeptPersonDto().getId(),
                    modifiedSession.getToken(),
                    SystemConstants.EMPTY_STR,
                    SystemConstants.LoginType.JS_API.getType().equals(modifiedSession.getLoginType())
                            ? EmpSystemConstants.EMP_EXPIRE_TIME : EmpSystemConstants.EMP_APP_EXPIRE_TIME,
                    TimeUnit.SECONDS
            );
            modifiedSession.getDeptPersonDto().setPassword(null);

            //设置可访问角色
            ApiDeptPersonService apiDeptPersonService = SpringUtils.getBean(ApiDeptPersonService.class);
            Preconditions.checkNotNull(apiDeptPersonService);
            Set<String> resources = apiDeptPersonService.queryResourcesById(modifiedSession.getDeptPersonDto().getId());
            modifiedSession.setResources(resources);
        }

        RedisUtils.set(
                EmpSystemConstants.TOKEN_EMP_SESSION + modifiedSession.getToken(),
                JacksonUtils.toJsonString(modifiedSession),
                SystemConstants.LoginType.JS_API.getType().equals(modifiedSession.getLoginType())
                        ? EmpSystemConstants.EMP_EXPIRE_TIME : EmpSystemConstants.EMP_APP_EXPIRE_TIME,
                TimeUnit.SECONDS
        );

        //不返回前端
        modifiedSession.setOfficialAccountsType(null);
        modifiedSession.setAppId(null);
        modifiedSession.setOpenId(null);
        return modifiedSession;
    }


    /**
     * 删除用户的token
     *
     * @param id
     */
    public static void removeUserToken(Long id) {
        //需要踢出已经授权的token
        Map<String, String> tokens = RedisUtils.hGetAll(EmpSystemConstants.EMP_TOKEN_SESSION + id);
        if (tokens != null) {
            tokens.forEach((k, v) -> RedisUtils.del(EmpSystemConstants.TOKEN_EMP_SESSION + k));
        }
        RedisUtils.del(EmpSystemConstants.EMP_TOKEN_SESSION + id);
    }

    /**
     * 退出当前session
     */
    public static void logout() {
        LoginEmpSession session = getLoginEmpSession();
        //删除token绑定人员
        RedisUtils.del(EmpSystemConstants.TOKEN_EMP_SESSION + session.getToken());
        //删除人员所绑定的当前token
        RedisUtils.hDel(EmpSystemConstants.EMP_TOKEN_SESSION + session.getDeptPersonDto().getId(), session.getToken());
    }
}
